/* fc_layer.h */
#ifndef __FC_LAYER_H__
#define __FC_LAYER_H__

#include <stdint.h>
#include <stdbool.h>

/* 本例中实现的全连接层, 使用tanh作为激活函数, 反向求导的解析式是1/(x^2). */

typedef struct
{
    uint32_t dim_in;  /* 本层输入向量的维度. */
    uint32_t dim_out; /* 本层输出向量的维度. */
    float *W;         /* 本层的权重矩阵, W[dim_in][dim_out]. */
    float *B;         /* 本层的偏置矩阵, biases[dim_out]. */

    /* 主要用于反向求导. 变量命名中的d为delta的缩写.*/
    float *dW; /* 保存即将要更新到权重矩阵的学习增量, dW[dim_in][dim_out]. */
    float *dB; /* 保存即将要更新的偏置向量的学习增量, dB[dim_out]. */
    //float *dO; /* 预测输出偏差, dO[dim_out]. 就是预测输出同实际输出的差值. */
    //float *val_in; /* 本层的输入向量, val_in[dim_in]. 更多用于保存上一层的输出. */

} fc_layer_t;

void arm_exp_f32(float *input, float *output, uint32_t len);
void arm_div_f32(float *input1, float *input2, float *output, uint32_t len);
void arm_tanh_f32(float *input, float *output, uint32_t len);
void arm_dtanh_f32(float *input, float *output, uint32_t len);
void arm_rand_f32(float *output, float min, float max, uint32_t len);

void fc_layer_new_infer(fc_layer_t *layer, uint32_t dim_in, uint32_t dim_out, float *W, float *B);
void fc_layer_infer(fc_layer_t *layer, float *val_in, float *val_out);
bool fc_layer_new_backprop(fc_layer_t *layer, uint32_t dim_in, uint32_t dim_out, float *dW, float *dB);
void fc_layer_clear_gradients(fc_layer_t *layer);
void fc_layer_backprop(fc_layer_t *layer, float *prv_out, float *prv_err, float *in_val, float *in_err);
void fc_layer_update(fc_layer_t *layer, float learn_rate);

#endif /* __FC_LAYER_H__ */

